package com.iussoft.tdengine.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.iussoft.tdengine.util.StringUtil;
import com.iussoft.tdengine.util.TDengineUtil;


import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;

/**
 * @description: 动态多数据源
 * @author: Hou Dayu
 * @date: Created in 2020/11/6
 */
public class MultipleDataSource extends AbstractDataSource {

    @Override
    public void afterPropertiesSet() {

        buildDefaultDatasource();
        if(StringUtil.isNotNull(datasourceKeys)){
            String dskey[] = datasourceKeys.split(",");
            int count = dskey.length;
            if(this.targetDataSources == null){
                this.targetDataSources = new Hashtable();
            }
            for(int i=0; i<count; i++){
                String key = dskey[i];
                String cacheKey =key;
                if(StringUtil.isNull(TDengineUtil.TDDB_CACHE_NAME)){
                    cacheKey = TDengineUtil.TDDB_CACHE_PREFIX_NAME + key;
                }
                Object obj = LoadCacheFactory.getInstance().getCacheManager(TDengineUtil.TDDB_CACHE_NAME).getCacheObjectByKey(cacheKey);
                if(obj == null){
                    continue;
                }
                JSONObject dbJson = (JSONObject)JSON.toJSON(obj);
                DruidDataSource db = getDataSource(dbJson);
                if(null == defaultDataSource){
                    defaultDataSource = db;
                    setDatasourceKey(key);
                }
                targetDataSources.put(key, db);
            }
        }

        if (this.targetDataSources == null || targetDataSources.isEmpty()) {
            throw new IllegalArgumentException("Property 'targetDataSources' is required");
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        return determineTargetDataSource().getConnection();
    }

    public Connection getConnection(String datasourceKey) throws SQLException {
        if(StringUtil.isNull(datasourceKey) || !this.targetDataSources.containsKey(datasourceKey))
            return getConnection();
        return this.targetDataSources.get(datasourceKey).getConnection();
    }

    public void addDatasource(String datasourceKey, JSONObject dbJson){
        DruidDataSource db = getDataSource(dbJson);
        targetDataSources.put(datasourceKey, db);
    }

    public DataSource getDatasource(String datasourceKey){
        return targetDataSources.get(datasourceKey);
    }

    public boolean checkDataSource(String datasourceKey){
        return targetDataSources.containsKey(datasourceKey);
    }

    public synchronized boolean removeDataSource(String datasourceKey){
        targetDataSources.remove(datasourceKey);
        return true;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return TDDataSourceHolder.getDataSouce();
    }

    private DruidDataSource getDataSource(JSONObject dbJson){
        String driver = dbJson.getString("driverClassName");
        String url = dbJson.getString("url");
        String username = dbJson.getString("username");
        String password = dbJson.getString("password");
        int maxActive = Integer.parseInt(StringUtil.doNull(dbJson.getString("maxActive"),"0"));
        int maxWate = Integer.parseInt(StringUtil.doNull(dbJson.getString("maxWate"),"0"));
        int minIdle = Integer.parseInt(StringUtil.doNull(dbJson.getString("minIdle"),"0"));
        int initialSize = Integer.parseInt(StringUtil.doNull(dbJson.getString("initialSize"),"0"));
        DruidDataSource db = this.initDataSource(url,driver,username,password);
        if(maxActive>0)
            db.setMaxActive(maxActive);
        if(maxWate>0)
            db.setInitialSize(maxWate);
        if(minIdle>0)
            db.setMinIdle(minIdle);
        if(initialSize>0)
            db.setMaxWait(initialSize);
        return db;
    }
}
